package com.aqie.seller.service;

import com.aqie.api.ProductRpc;
import com.aqie.api.domain.ProductRpcReq;
import com.aqie.api.events.ProductStatusEvent;
import com.aqie.entity.Product;
import com.aqie.entity.enums.ProductStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

/**
 * 产品相关服务
 */
@Service
public class ProductRpcService implements ApplicationListener<ContextRefreshedEvent> {  // 容器初始化会触发事件
    private static final Logger LOG = LoggerFactory.getLogger(ProductRpcService.class);
    // 注入rpc 服务,添加配置类,告诉spring 连接服务端 ,
    // 配置文件：api/application.yml
    // 配置类
    @Autowired
    private ProductRpc productRpc;

    // 前缀Consumer 分组 cache
    static final String MQ_DESTINATION = "Consumer.cache.VirtualTopic.PRODUCT_STATUS";

    // 注入缓存类
    @Autowired
    private ProductCache productCache;

    // 初始化方法
    @PostConstruct
    public void init(){
        findAll();
    }
    /**
     * 查询全部产品
     * 所有数据倒数从缓存中优先读取
     * 问题： 开始没有缓存全部数据，只调用findOne，会读取中部分产品
     *         要求系统初始化就缓存全部数据
     * @return
     */
    public List<Product> findAll() {
        return productCache.readAllCache();
    }

    /**
     * 如果缓存为空,使用清除缓存,缓存中不会有空数据
     * 这里不用cacheable 注解，不然还是会添加缓存
     * @param id
     * @return
     */
    public Product findOne(String id){
        Product product = productCache.readCache(id);
        if (product == null) {
            productCache.removeCache(id);
        }
        return product;
    }
    // 类似单元测试
    @PostConstruct
    public void testFindAll(){
        findAll();
        findOne("1");
    }

    // 初始化缓存中数据
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        List<Product> products = findAll();
        // 遍历所有产品放入缓存中
        products.forEach(product -> productCache.putCache(product));
    }

    // 添加监听产品状态变化事件
    @JmsListener(destination = MQ_DESTINATION)
    void updateCache(ProductStatusEvent event) {    // 接收事件改变事件
        LOG.info("receive event:{}", event);
        productCache.removeCache(event.getId());    // 先清空缓存
        if (ProductStatus.IN_SELL.equals(event.getStatus())) {
            productCache.readCache(event.getId());
        }
    }
}
